package  
{
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import mge.Utils;
  // import away3d.events.AssetEvent;
	/**
   * ...
   * @author ivan
   */
  public class HeightMapTexture 
  {
    [Embed(source = '../embeds/sand_128.jpg')]
    private var rSand:Class;
    [Embed(source = '../embeds/water_128.jpg')]
    private var rWater:Class;
    [Embed(source = '../embeds/grass_128.jpg')]
    private var rGrass:Class;
    [Embed(source = '../embeds/rock_128.jpg')]
    private var rRock:Class;
    
    // Texture size must be small enought.
    // @region Region of the height map that will be covered by the generated BitmapData.
    public function HeightMapTexture(heightMapBitmapData:flash.display.BitmapData, region:flash.geom.Rectangle)
    {
      var hm:HeightMap = new HeightMap(heightMapBitmapData, region, 0, 0);
      
      if (!textures)
      {
        textures = new Vector.<flash.display.BitmapData>();
        //textures.push((new rWater() as flash.display.Bitmap).bitmapData);
        textures.push((new rSand() as flash.display.Bitmap).bitmapData);
        textures.push((new rSand() as flash.display.Bitmap).bitmapData);
        textures.push((new rGrass() as flash.display.Bitmap).bitmapData);
        textures.push((new rRock() as flash.display.Bitmap).bitmapData);
      }
      
      var size:int = textures[0].width;
      
      // Build texture
      bmp = new flash.display.BitmapData(size, size, false);
      for (var i:int = 0; i < size; i++)
      for (var j:int = 0; j < size; j++)
      {
        var di:Number = i / size;
        var dj:Number = j / size;
        
        //var h:Number = heightMapBitmapData.getPixel(Utils.interpolate(region.left, region.right, di), Utils.interpolate(region.top, region.bottom, dj)) >> 16 & 0xFF;
        //h /= 256;
        var h:Number = hm.heightAtMapPosition(Utils.interpolate(region.left, region.right, di), Utils.interpolate(region.top, region.bottom, dj));
        h /= hm.maxHeight;
        
        
        bmp.setPixel(i, j, weight(h, new flash.geom.Point(Utils.interpolate(0, bmp.width, di), 
                                                          Utils.interpolate(0, bmp.height, dj))));
      }
    }
    
    private function weight(h:Number, point:flash.geom.Point):Number
    {
      var values:Array = 
      [
        0,      
        0.1,    // water
        0.15,   // sand
        0.85,   // rock 
        1
      ]
      
      for (var i:int = 1; i < values.length; i++)
      {
        if (h < values[i])
        {
          var ta:flash.display.BitmapData = textures[i - 1];
          var tb:flash.display.BitmapData = textures[Math.min(i, textures.length-1)];
          
          var c1:uint = ta.getPixel(point.x, point.y);
          var r1:uint = c1 >> 16 & 0xFF;
          var g1:uint = c1 >> 8 & 0xFF;
          var b1:uint = c1 & 0xFF;
          
          var c2:uint = tb.getPixel(point.x, point.y);
          var r2:uint = c2 >> 16 & 0xFF;
          var g2:uint = c2 >> 8 & 0xFF;
          var b2:uint = c2 & 0xFF;
          
          var interpolate:Number = Utils.interpolateInv(values[i - 1], values[i], h);
          
          var result:uint = (r1 * (1 - interpolate) + r2 * interpolate) << 16 |
                            (g1 * (1 - interpolate) + g2 * interpolate) << 8 |
                            (b1 * (1 - interpolate) + b2 * interpolate);
                            
          return result;
        }
      }
      
      return 0;
    }
    
    public function get bitmapData():flash.display.BitmapData { return bmp; }
    
    private var bmp:flash.display.BitmapData;
    private static var textures:Vector.<flash.display.BitmapData>;
    
  }

}